package org.jeie.main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Vector;

public class Canvas {
	private BufferedImage renderedImage;
	private BufferedImage baseImage;
	private int zoom = 1;
	private Vector<Action> acts;
	private int index = 0;
	public boolean drawGrid = true;

	public Canvas(BufferedImage baseImage) {
		acts = new Vector<Action>();
		this.baseImage = baseImage;
		render();
	}

	public void doAction(Action act) {
		for (int i = index + 1; i < acts.size(); i++) {
			acts.remove(i);
		}
		acts.add(act);
		index++;
		render();
		EasyImageEditor.mainPanel.gui.repaint();
	}

	public void undo() {
		if (index > 0)
			index--;
		render();
		EasyImageEditor.mainPanel.gui.repaint();

	}

	public void redo() {
		if (index < acts.size() - 2)
			index++;
		render();
		EasyImageEditor.mainPanel.gui.repaint();
	}

	public void setZoom(int zoom) {
		this.zoom = zoom;
		render();
	}

	public void zoomIn() {
		if (zoom < 32) {
			zoom *= 2;
			render();
		}
	}

	public void zoomOut() {
		if (zoom > 1) {
			zoom /= 2;
			render();
		}
	}

	public int getZoom() {
		return zoom;
	}

	public int getHeight() {
		return renderedImage.getHeight();
	}

	public int getWidth() {
		return renderedImage.getWidth();
	}

	public BufferedImage saveRender(boolean doZoom) {
		BufferedImage img = new BufferedImage(baseImage.getWidth(),
				baseImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
		img.createGraphics().drawImage(baseImage, 0, 0, null);
		// do render
		for (int i = 0; i < acts.size(); i++) {
			if (i > index)
				break;
			img = acts.get(i).apply(img);
		}

		if (doZoom) {
			img = resize(img, img.getWidth() * zoom, img.getHeight() * zoom);
		}
		return img;
	}

	private void render(boolean doZoom) {
		renderedImage = saveRender(doZoom);
	}

	private void render() {
		render(true);
	}

	public Color colorAtPoint(Point p) {
		return new Color(renderedImage.getRGB(p.x * zoom, p.y * zoom));
	}

	public void paint(Graphics g, int x, int y) {
		g.drawImage(renderedImage, x, y, null);
	}

	public static BufferedImage resize(BufferedImage source, int newW, int newH) {
		BufferedImage scaledImage = new BufferedImage(newW, newH,
				source.getType());
		Graphics2D graphics2D = scaledImage.createGraphics();
		/*
		 * graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
		 * RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		 */
		graphics2D.drawImage(source, 0, 0, newW, newH, null);
		graphics2D.dispose();
		return scaledImage;
	}

	public Point screenToImage(Point p) {
		return new Point((int) (p.x / zoom), (int) p.y / zoom);
	}

	public void clearActions() {
		render(false);
		baseImage = renderedImage;
		acts.clear();
	}
}
